package com.sun.aop;

import com.sun.listen.SysLogEvent;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;


/**
 * 自定义Exception的aop操作
 */
@Component
@Aspect
@Slf4j
public class LogAop implements ApplicationEventPublisherAware {

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private ApplicationEventPublisher publisher;

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }


    @Pointcut("@annotation(com.sun.annotation.Log)")
    public void logAop() {
    }

    @Before("logAop()")
    public void beforeLog() {
        log.info("日志监控Aop开始>>>>>>>>>>>>>>>>>");
    }


    @AfterReturning(value = "logAop()", returning = "returnValue")
    public void afterLog(JoinPoint joinPoint, Object returnValue) {
        log.info("@AfterReturning：日志记录功能start>>>>>>>>>>");
        log.info("@AfterReturning：目标方法为：" +
                joinPoint.getSignature().getDeclaringTypeName() +
                "." + joinPoint.getSignature().getName());
        log.info("@AfterReturning：参数为：" +
                Arrays.toString(joinPoint.getArgs()));
        log.info("@AfterReturning：被织入的目标对象为：" + joinPoint.getTarget());
        log.info("@AfterReturning：返回值为：" + returnValue);
        log.info("@AfterReturning：日志记录功能end>>>>>>>>>>");
    }

    @AfterThrowing(value = "logAop()", throwing = "ex")
    public void exceptionLog(JoinPoint joinPoint, Exception ex) {
        log.info("@AfterThrowing：日志记录功能start>>>>>>>>>>");
        log.info("@AfterThrowing：目标方法为：" +
                joinPoint.getSignature().getDeclaringTypeName() +
                "." + joinPoint.getSignature().getName());
        log.info("@AfterThrowing：参数为：" +
                Arrays.toString(joinPoint.getArgs()));
        log.info("@AfterThrowing：被织入的目标对象为：" + joinPoint.getTarget());
        log.info("@AfterThrowing：异常结果为：[" + ex.getMessage() + "]");
        log.info("@AfterThrowing：日志记录功能end>>>>>>>>>>");
    }


    /**
     * 环绕通知
     * ProceedingJoinPoint etends JoinPoint
     */
    @Around(value = "logAop()")
    public Object test3(ProceedingJoinPoint proceedingJoinPoint) {
        Date now = new Date();
        String requestTime = dateFormat.format(now);
        Object proceed = null;
        //获取参数
        Object[] args = proceedingJoinPoint.getArgs();
        log.info("传递的参数为:" + args);
        try {
            //获取切入方法的返回值
            proceed = proceedingJoinPoint.proceed();
            log.info("@Around:返回的结果为:{}" + proceed);
            Date end = new Date();
            String responseTime = dateFormat.format(end);
            //发布监听程序
            SysLogEvent sysLogEvent = new SysLogEvent();
            sysLogEvent.setClassName(proceedingJoinPoint.getSignature().getDeclaringTypeName());
            sysLogEvent.setMethodName(proceedingJoinPoint.getSignature().getName());
            sysLogEvent.setOperateAuther("sunyuanhang");
            sysLogEvent.setRequestTime(requestTime);
            sysLogEvent.setResponseTime(responseTime);
            sysLogEvent.setReturnValue(proceed);
            //发布监听程序
            publisher.publishEvent(sysLogEvent);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return proceed;
    }
}
